﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using PSE.Updater.Client.Engine;
using PSE.Updater.Common;
using PSE.Updater.Common.Gateway.DataContract;
using PSE.Updater.Common.Providers;
using PSE.Framework.ErrorLogging;
using System.Drawing;
using System.Reflection;
using System.Windows.Media.Imaging;

namespace PSE.Updater.Client.Providers
{
    public abstract class UpdateBase
    {
        private const string CONST_TITLE_SYSTRAY = "BM&FBOVESPA";

        protected NotifyIcon _sytrayIcon = null;
        private Action _systrayDoubleClick = null;

        public Action OnClose { protected get; set; }

        public class DownloadedFile
        {
            public string Path { get; set; }
            public ModuleUpdatePackage ModuleUpdatePackage { get; set; }
        }

        protected IList<Engine.SystemInformation> InstalledSystems { get; set; }

        public ProviderType ProviderType { get; set; }

        public UpdateBase(ProviderType providerType)
        {
            InstalledSystems installedSystems = new InstalledSystems();
            this.InstalledSystems = installedSystems.List();

            this.ProviderType = providerType;
        }

        public void Initialize()
        {
            try
            {
                var downloadedFiles = new List<string>();
                var allAvailableUpdates = new List<ModuleUpdatePackage>();
                foreach (var system in this.InstalledSystems)
                {
                    var availableUpdates = GetAvailableUpdates(system);
                    if (availableUpdates != null && availableUpdates.Count > 0)
                        allAvailableUpdates.AddRange(availableUpdates);
                }

                if (allAvailableUpdates == null || allAvailableUpdates.Count == 0)
                {
                    if(this.OnClose != null)
                        this.OnClose();
                }
                else
                {
                    ShowUpdates(allAvailableUpdates);
                }
            }
            catch (Exception ex)
            {
                ErrorLogger.WriteLog(LogType.Error, ex);
                //throw ex;
            }
        }

        protected IList<DownloadedFile> BeginDownload(IList<ModuleUpdatePackage> availableUpdates)
        {
            string pkgFilePath = string.Empty;
            List<DownloadedFile> downloadedFiles = new List<DownloadedFile>();

            foreach (ModuleUpdatePackage pkg in availableUpdates)
            {
                try
                {
                    pkgFilePath = DoDownload(pkg);
                    if (string.IsNullOrEmpty(pkgFilePath))
                    {
                        //SendAlert("Download não efetuado");
                        pkg.Status = PackageStatus.Missing;
                    }
                    else
                    {
                        if (!File.Exists(pkgFilePath))
                        {
                            //SendAlert("Caminho de arquivo inválido");
                            pkg.Status = PackageStatus.Invalid;
                        }
                    }
                    downloadedFiles.Add(new DownloadedFile { Path = pkgFilePath, ModuleUpdatePackage = pkg });
                }
                catch (Exception ex)
                {
                    SendAlert(ex.Message);
                    pkg.Status = PackageStatus.Invalid;
                    downloadedFiles.Add(new DownloadedFile { Path = string.Empty, ModuleUpdatePackage = pkg });
                }
            }
            return downloadedFiles;
        }

        private string DoDownload(ModuleUpdatePackage pkg)
        {
            Service.Proxy.Instance.DownloadProgressChanged += ((sender, e) =>
            {
                DownloadProgressChanged(pkg, e.Progress);
            });
            return Service.Proxy.Instance.DownloadUpdatePackage(this.ProviderType, pkg);
        }

        protected List<ModuleVersion> ConvertToModulesDataContract(string systemName, List<ModuleDetails> modules)
        {
            List<ModuleVersion> modulesDataContract = new List<ModuleVersion>();

            foreach (var module in modules)
                modulesDataContract.Add(new ModuleVersion
                {
                    SystemName = systemName,
                    ModuleName = module.ModuleName,
                    Version = module.Version
                });

            return modulesDataContract;
        }

        protected void ShowSytrayIcon(string balloonTipText, string text, Action onDoubleClick)
        {
            ShowSytrayIcon(balloonTipText, text, onDoubleClick, ToolTipIcon.Info);
        }

        protected void ShowSytrayIcon(string balloonTipText, string text, Action onDoubleClick, ToolTipIcon icon)
        {
            if (_sytrayIcon == null)
            {
                _sytrayIcon = new NotifyIcon();

                Icon imageIcon = GetIcon();
                if (imageIcon != null)
                    _sytrayIcon.Icon = imageIcon;
                _sytrayIcon.BalloonTipIcon = icon;
            }

            _systrayDoubleClick = onDoubleClick;
            _sytrayIcon.BalloonTipText = text;
            _sytrayIcon.BalloonTipTitle = CONST_TITLE_SYSTRAY;
            _sytrayIcon.Text = balloonTipText;
            _sytrayIcon.Visible = true;
            _sytrayIcon.DoubleClick += new EventHandler(_sytrayIcon_DoubleClick);

            _sytrayIcon.ShowBalloonTip(10000);
        }

        private void _sytrayIcon_DoubleClick(object sender, EventArgs e)
        {
            if (_systrayDoubleClick != null)
            {
                _sytrayIcon.DoubleClick -= new EventHandler(_sytrayIcon_DoubleClick);
                _systrayDoubleClick();
                _sytrayIcon.Dispose();
            }
        }

        public Icon GetIcon()
        {
            MemoryStream memoryStream = new MemoryStream();
            System.Drawing.Icon icon = null;
            Stream stream = null;

            Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();

            foreach (string resource in entryAssembly.GetManifestResourceNames())
            {
                if (resource.EndsWith(".ico"))
                {
                    stream = entryAssembly.GetManifestResourceStream(resource);
                    break;
                }
            }

            if (stream != null)
            {
                icon = new System.Drawing.Icon(stream);
            }
            return icon;
        }
        protected void HideSytrayIcon()
        {
            _sytrayIcon.Visible = false;
            _sytrayIcon.Dispose();
        }

        protected abstract void DownloadProgressChanged(ModuleUpdatePackage pkg, int progress);
        protected abstract void ShowUpdates(List<ModuleUpdatePackage> modules);
        protected abstract List<ModuleUpdatePackage> GetAvailableUpdates(Engine.SystemInformation system);

        private void SendAlert(string message)
        {

        }
    }
}